package com.ruge.tool.file;

import com.ruge.tool.str.StringTool;
import lombok.NoArgsConstructor;
import org.apache.commons.io.FileUtils;

import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.text.Collator;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Map;

/**
 * file工具类
 *
 * @author ruge.wu
 * @since 2021-10-08 14:41
 **/
@NoArgsConstructor
public class FileTool extends FileUtils {
    /**
     * 文件 关键字替换
     *
     * @param file 文件
     * @param maps 关键字集合 key value
     */
    public static void replaceKeyWord(File file, Map<String, String> maps) {
        maps.forEach((k, v) -> {
            try {
                FileReader fileReader = new FileReader(file);
                // 创建缓冲字符数组
                char[] data = new char[1024];
                StringBuilder sb = new StringBuilder();
                // 读取的字符数，如果已到达流的末尾，则返回 -1
                int rn;
                while ((rn = fileReader.read(data)) > 0) { // 读取文件内容到字符串构建器
                    String str = String.valueOf(data, 0, rn);// 把数组转换成字符串
                    sb.append(str);
                }
                // 生成字符串，并替换搜索文本
                String str = sb.toString().replace(k, v);
                // 创建文件输出流
                FileWriter fileWriter = new FileWriter(file);
                // 把替换完成的字符串写入文件内
                fileWriter.write(str.toCharArray());
                // 关闭文件流，释放资源
                fileReader.close();
                fileWriter.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        });

    }

    /**
     * 遍历文件夹下所有文件
     *
     * @param file    文件集合
     * @param results 遍历文件夹下所有文件
     */
    public static void listFile(File file, List<File> results) {
        File[] files = file.listFiles();
        orderByName(files);
        assert files != null;
        for (File f : files) {
            //若是目录，则递归打印该目录下的文件
            if (f.isDirectory()) {
                listFile(f, results);
            }
            //若是文件，直接打印
            if (f.isFile()) {
                results.add(f);
            }
        }
    }

    /**
     * 按照名称排序文件
     *
     * @param fs 文件集合
     */
    public static void orderByName(File[] fs) {
        List<File> files = Arrays.asList(fs);
        //这是比较方法（可比较中文，但对于生僻字，效果不太好）
        Comparator<Object> chinaCompare = Collator.getInstance(java.util.Locale.CHINA);
        files.sort((q1, q2) -> {
            String o1 = q1.getName();
            String o2 = q2.getName();
            //比较的基本原则，拿最小长度的字符串进行比较，若全部相等，则长字符串往后排
            int len1 = o1.length();
            int len2 = o2.length();
            int len = (len1 - len2) <= 0 ? len1 : len2;
            StringBuilder sb1 = new StringBuilder();
            StringBuilder sb2 = new StringBuilder();
            for (int i = 0; i < len; i++) {
                String s1 = o1.substring(i, i + 1);
                String s2 = o2.substring(i, i + 1);
                if (StringTool.isNumeric(s1) && StringTool.isNumeric(s2)) {
                    //取出所有的数字
                    sb1.append(s1);
                    sb2.append(s2);
                    //取数字时，不比较
                    continue;
                }
                if (sb1.length() != 0 && sb2.length() != 0) {
                    if (!StringTool.isNumeric(s1) && !StringTool.isNumeric(s2)) {
                        long value1 = Long.parseLong(sb1.toString());
                        long value2 = Long.parseLong(sb2.toString());
                        if (value1 - value2 > Integer.MAX_VALUE) {
                            return 1;
                        } else if (value1 - value2 < Integer.MIN_VALUE) {
                            return -1;
                        }
                        return (int) (value1 - value2);
                    } else if (StringTool.isNumeric(s1)) {
                        return 1;
                    } else if (StringTool.isNumeric(s2)) {
                        return -1;
                    }
                }
                int result = chinaCompare.compare(s1, s2);
                if (result != 0) {
                    return result;
                }
            }
            //这一步：是为了防止以下情况：第10  第20，正好以数字结尾，且字符串长度相等
            if (len1 == len2 && sb1.length() != 0 && sb2.length() != 0) {
                long value1 = Long.parseLong(sb1.toString());
                long value2 = Long.parseLong(sb2.toString());
                if (value1 - value2 > Integer.MAX_VALUE) {
                    return 1;
                } else if (value1 - value2 < Integer.MIN_VALUE) {
                    return -1;
                }
                return (int) (value1 - value2);
            }
            //若前面都相等，则直接比较字符串的长度，长的排后面，短的排前面
            return Integer.compare(len1, len2);
        });
    }

    /**
     * 按照文件日期排序
     *
     * @param fs 文件集合
     */
    public static void orderByDate(File[] fs) {
        List<File> files = Arrays.asList(fs);
        files.sort(Comparator.comparing(File::lastModified));
    }

    /**
     * 按照文件大小排序
     *
     * @param fs 文件集合
     */
    public static void orderByLength(File[] fs) {
        List<File> files = Arrays.asList(fs);
        files.sort(Comparator.comparing(File::length));
    }

    public static void listFile(String path, Boolean deep, List<String> fileNames) {
        File file = new File(path);
        String[] names = file.list();
        for (int i = 0; i < names.length; i++) {
            String oldFileName = names[i];
            if (null != deep && deep) {
                String oldFilePath = path.concat("\\").concat(oldFileName);
                File oldFile = new File(oldFilePath);
                fileNames.add(oldFileName);
                if (oldFile.isDirectory()) {
                    listFile(oldFilePath, true, fileNames);
                }
            }
        }

    }

    /**
     * 文件名重命名
     *
     * @param path        文件的上一层目录路径
     * @param oldFileName 要修改的文件旧路径
     * @param newFileName 新的文件路径
     * @return 成功返回true, 失败返回false
     * @author only-dream
     */
    public static boolean renameFile(String path, String oldFileName, String newFileName) {
        // 新的文件名和以前文件名不同时,才有必要进行重命名
        if (!oldFileName.equals(newFileName)) {
            File oldfile = new File(path + "/" + oldFileName);
            File newfile = new File(path + "/" + newFileName);
            // 若在该目录下已经有一个文件和新文件名相同，则不允许重命名
            if (newfile.exists()) {
                return false;
            } else {
                oldfile.renameTo(newfile);
                return true;
            }
        }
        System.out.println("文件名称一致");
        return false;
    }

    /**
     * 文件重命名
     *
     * @param file        file
     * @param newFileName 新的文件名称
     * @return 文件重命名
     */
    public static boolean rename(File file, String newFileName) {
        // 新的文件名和以前文件名不同时,才有必要进行重命名
        File fileParentFile = file.getParentFile();
        return file.renameTo(new File(fileParentFile + "/" + newFileName));
    }

    /**
     * 获取文件拓展名
     *
     * @param file 文件
     * @return 文件拓展名
     */
    public static String getExtension(File file) {
        String fileName = file.getName();
        return fileName.substring(fileName.lastIndexOf('.') + 1, fileName.length());
    }


    /**
     * 获取文件名称
     *
     * @param file 文件
     * @return 文件名称
     */
    public static String getFileName(String file) {
        return file.substring(file.lastIndexOf('/') + 1, file.lastIndexOf('.'));
    }

    /**
     * 新建文件夹
     *
     * @param path 文件夹路径
     */
    public static void mkdirs(String path) {
        File file = new File(path);
        file.mkdirs();
    }
}
